package com.bobamrz.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import com.bobamrz.model.Camera;



public class CameraDAO {
	
	private Logger log = Logger.getLogger(CameraDAO.class);
	
	public static final String SELECT_ALL_SQL = 
			"SELECT * " +
			"FROM Camera";
	
	public static final String SELECT_BY_ID_SQL = 
			"SELECT * " +
			"FROM Camera " +
			"WHERE id = ?";
	
	public static final String UPDATE_SQL = 
			"UPDATE CAMERA SET " +
			"(model, sensor_resolution_in_megapixels, description) = " +
			"(?, ?, ?) " +
			"WHERE id = ?";
	
	private static final SessionFactory sessionFactory;
	
	static {
	      try {
	        sessionFactory = new Configuration().configure().buildSessionFactory();
	      } catch (Throwable ex) {
	        System.err.println("Initial SessionFactory creation failed." + ex);
	        throw new ExceptionInInitializerError(ex);
	      }
	    }
	
	private Connection connection;
	private PreparedStatement selectAllStatement;
	private PreparedStatement selectByIdStatement;
	private PreparedStatement updateStatement;
	
	public CameraDAO(Connection connection) {
		this.connection = connection;
		try {
			selectAllStatement = connection.prepareStatement(SELECT_ALL_SQL);
			selectByIdStatement = connection.prepareStatement(SELECT_BY_ID_SQL);
			updateStatement = connection.prepareStatement(UPDATE_SQL);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}
		
	
	public void dispose() {
		try {
			connection.close();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}
	
	public List<Camera> findAll() {
		List<Camera> cameras = null;
		try {
			ResultSet resultSet = selectAllStatement.executeQuery();
			cameras = convertResultSetToCameras(resultSet);
			
			log.debug(selectAllStatement.toString());
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
		return cameras;
	}
	
	public Camera findById(int id) {
		Camera camera = null;
		try {
			selectByIdStatement.setInt(1, id);
			ResultSet resultSet = selectByIdStatement.executeQuery();
			resultSet.next();
			camera = createCamera(resultSet);
			
			log.debug(selectByIdStatement.toString());
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
		return camera;
	}
	
	public void update(Camera camera) {
		try {
			/*updateStatement.setInt(4, camera.getId());
			updateStatement.setString(1, camera.getModel());
			updateStatement.setDouble(2, camera.getSensorResolutionInMegapixels());
			updateStatement.setString(3, camera.getDescription());
			updateStatement.executeUpdate();
			
			log.debug(updateStatement.toString());*/
			
			Session session = sessionFactory.openSession();
			session.beginTransaction();
			session.save( camera );
			session.getTransaction().commit();
			session.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
	}
	
	private List<Camera> convertResultSetToCameras(ResultSet resultSet) throws SQLException {
		List<Camera> cameras = new ArrayList<Camera>();
		while(resultSet.next()) {
			Camera camera = createCamera(resultSet);
			cameras.add(camera);
		}
		return cameras;
	}

	private Camera createCamera(ResultSet resultSet) throws SQLException {
		int id = resultSet.getInt("id");
		String model = resultSet.getString("model");
		double sensorResolution = resultSet.getDouble("sensor_resolution_in_megapixels");
		String description = resultSet.getString("description");
		
		Camera camera = new Camera(id, model, sensorResolution, description);
		return camera;
	}

}
